package com.hvgroup.modules.sanic.service.impl;

import com.hvgroup.modules.sanic.constants.DiFyRestApi;
import com.hvgroup.modules.sanic.domain.dto.QaMessageDto;
import com.hvgroup.modules.sanic.domain.dto.QaSessionDto;
import com.hvgroup.modules.sanic.domain.po.LlmApp;
import com.hvgroup.modules.sanic.domain.po.QaMessage;
import com.hvgroup.modules.sanic.domain.po.QaSession;
import com.hvgroup.modules.sanic.repository.LlmAppRepository;
import com.hvgroup.modules.sanic.repository.QaMessageRepository;
import com.hvgroup.modules.sanic.repository.QaSessionRepository;
import com.hvgroup.modules.sanic.service.ConvService;
import com.hvgroup.modules.sanic.service.mapstruct.QaMessageMapper;
import com.hvgroup.modules.sanic.service.mapstruct.QaSessionMapper;
import com.hvgroup.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
@RequiredArgsConstructor
public class ConvServiceImpl implements ConvService {

//    @Value("${dify.api.key.app}")
//    private String difyApiKey;

    @Value("${dify.api.url.root}")
    private String difyApiUrl;

    //    private final UserQaRecordRepository userQaRecordRepository;
    private final QaSessionRepository qaSessionRepository;
    private final QaMessageRepository qaMessageRepository;
    private final LlmAppRepository llmAppRepository;

    //    private final UserQaRecordMapper userQaRecordMapper;
    private final QaSessionMapper qaSessionMapper;
    private final QaMessageMapper qaMessageMapper;
//    private final ApiTokenRepository apiTokenRepository;


    @Override
    public List<Map<String, List<QaSessionDto>>> groupSessions(Long userId, Map<String, String> request) {
        String name = request.get("title");
//        String appId = request.get("appId");
        List<String> appIds = new ArrayList<>();
        String isCommQa = String.valueOf(request.get("isCommQa"));
        if ("true".equals(isCommQa)) {
            appIds = llmAppRepository.findAllByIsCommQa(true).stream().map(LlmApp::getAppId).collect(Collectors.toList());
        } else {
//            String appId = request.get("appId");
            appIds.add(request.get("appId"));
        }


        final List<String> _appIds = appIds;
        List<QaSession> list = qaSessionRepository.findAll((root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (userId != null) {
                predicates.add(cb.equal(root.get("userId"), userId));
            }
            if (StringUtils.isNotEmpty(name)) {
                predicates.add(cb.like(root.get("title"), "%" + name + "%"));
            }
//            if (StringUtils.isNotEmpty(appId)) {
//                predicates.add(cb.equal(root.get("appId"), appId ));
//            }
            CriteriaBuilder.In<String> inClause = cb.in(root.get("appId"));
            _appIds.forEach(inClause::value);
            predicates.add(inClause);

            query.orderBy(cb.desc(root.get("createTime")));
            return cb.and(predicates.toArray(new Predicate[0]));
        });

        LocalDate today = LocalDate.now();
        LocalDate weekStart = today.with(DayOfWeek.MONDAY);
        LocalDate monthStart = today.withDayOfMonth(1);
        LocalDate yearStart = today.withDayOfYear(1);

        Map<String, List<QaSessionDto>> resultMap = new LinkedHashMap<>();
        resultMap.put("今天", new ArrayList<>());
        resultMap.put("本周", new ArrayList<>());
        resultMap.put("本月", new ArrayList<>());
        resultMap.put("今年", new ArrayList<>());
        resultMap.put("更久之前", new ArrayList<>());

        for (QaSession session : list) {
            LocalDate date = session.getCreateTime().toLocalDateTime().toLocalDate();

            if (date.isEqual(today)) {
                resultMap.get("今天").add(qaSessionMapper.toDto(session));
            } else if (!date.isBefore(weekStart)) {
                resultMap.get("本周").add(qaSessionMapper.toDto(session));
            } else if (!date.isBefore(monthStart)) {
                resultMap.get("本月").add(qaSessionMapper.toDto(session));
            } else if (!date.isBefore(yearStart)) {
                resultMap.get("今年").add(qaSessionMapper.toDto(session));
            } else {
                resultMap.get("更久之前").add(qaSessionMapper.toDto(session));
            }
        }

        List<Map<String, List<QaSessionDto>>> resultList = new ArrayList<>();
        resultMap.forEach((k, v) -> {
            Map<String, List<QaSessionDto>> map = new HashMap<>();
            map.put(k, v);
            resultList.add(map);
        });

        return resultList;
    }

    @Override
    public List<QaSessionDto> searchUserRecord(Long userId, Map<String, String> map) {
        String title = map.get("title");
        String appId = map.get("appId");

        List<QaSession> list = qaSessionRepository.findAll((root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (userId != null) {
                predicates.add(cb.equal(root.get("userId"), userId));
            }
            if (StringUtils.isNotEmpty(title)) {
                predicates.add(cb.like(root.get("title"), "%" + title + "%"));
            }
            if (StringUtils.isNotEmpty(appId)) {
                predicates.add(cb.equal(root.get("appId"), appId ));
            }
            query.orderBy(cb.desc(root.get("createTime")));
            return cb.and(predicates.toArray(new Predicate[0]));
        });

        return list.stream().map(qaSessionMapper::toDto).collect(Collectors.toList());
    }

    @Override
    public List<QaMessageDto> getMessageList(long userId, long chatId) {
        return qaMessageRepository.findAllByChatIdOrderByCreateTimeAsc(chatId)
                .stream()
                .map(qaMessageMapper::toDto)
                .collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteUserRecord(Long userId, List<Long> recordIds) {
        qaSessionRepository.deleteAllByChatIdInAndUserId(recordIds, userId);
    }


    @Override
    public Object sendDifyFeedback(Map<String, String> request, Long userId) {
        try {
//            String chatId = request.get("chat_id");
            Integer rating = Integer.valueOf(request.get("rating"));
            Long feadId = Long.valueOf(request.get("feadId"));

            QaMessage qaMessage = qaMessageRepository.findById(feadId).orElseThrow(() -> new RuntimeException("会话不存在"));
            qaMessage.setRating(rating);
            qaMessageRepository.save(qaMessage);
            // 查询对话记录
//            List<UserQaRecordDto> qaRecordList = queryUserQaRecord(chatId); // 你需要实现
//            if (qaRecordList == null || qaRecordList.isEmpty()) {
//                throw new RuntimeException("chatId 不存在");
//            }

            String messageId = qaMessage.getMessageId();

            Map<String, Object> params = new HashMap<>();
            params.put("message_id", messageId);

            // 构建 URL
            String url = difyApiUrl + DiFyRestApi.replacePathParams(DiFyRestApi.DIFY_REST_FEEDBACK, params);

            QaSession qaSession = qaSessionRepository.findById(qaMessage.getChatId()).orElseThrow(() -> new RuntimeException("会话不存在"));
            // 获取 API KEY
            // TODO 2025年6月9日, 删除了直连dify
//            String apiKey = System.getenv("DIFY_DATABASE_QA_API_KEY");
//            ApiToken apiToken = apiTokenRepository.findFirstByAppId(UUID.fromString(qaSession.getAppId()).toString()).orElseThrow(() -> new RuntimeException("<UNK>"));

            // 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            // TODO 2025年6月9日, 删除了直连dify
//            headers.set("Authorization", "Bearer " + apiToken.getToken());

            // 请求体 payload
            Map<String, Object> payload = new HashMap<>();
            payload.put("rating", Integer.valueOf(1).equals(rating) ? "like" : "dislike");
            payload.put("user", String.valueOf(userId));

            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(payload, headers);
            RestTemplate restTemplate = new RestTemplate();

            // 执行 POST 请求
            ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("Feedback successfully sent.");

            } else {
                log.error("Failed to send feedback. Status code: {}, body: {}",
                        response.getStatusCodeValue(), response.getBody());
                throw new RuntimeException("反馈提交失败");
            }
            return response.getBody();
        } catch (Exception e) {
            log.error("发送反馈失败", e);
            throw new RuntimeException("发送反馈失败", e);
        }
    }


}
